/*
 * dwr_structs.h
 *
 *  Created on: 20/05/2013
 *      Author: jose
 */


#ifndef DWR_STRUCTS_H_
#define DWR_STRUCTS_H_

#include "dwr_ipoque.h"
#include "dwr_misc.h"


/************************************************************
 * ESTRUCTURAS
 ************************************************************/

/*
 * Guarda los datos de un HTTP request
 */
struct request_st
{
	void * timestamp;		// Momento de emisión de la solicitud http

	/* http headers */
	DwrString * method;
	DwrString * resource;
	DwrString * host;
	DwrString * referer;

	/* tcp ipoque */
	u32 next_tcp_seq_nr[2];
    u32 seq;
    u32 ack_seq;

	/* tcp flags */
	u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1;

	struct request_st * next;		// referencia a otra URL ligada a la URL del nodo cabecera

	/* Actualiza campos del tipo DwrString */
	struct request_st * (*update_text_field) (struct request_st *,
			const char *, ipoque_int_one_line_struct_t *);
	/* Imprime request */
	void (* print) (struct request_st *);
};
typedef struct request_st Http_Request;


/*
 * Guarda los datos de un HTTP response
 */
struct response_st
{
	void * timestamp;		// Momento de emisión de la solicitud http

	/* http headers */
	unsigned code;				// Código numérico de la respuesta (Ej.: 200, 404, etc.)
	unsigned content_len;		// Longitud de la respuesta
	DwrString * message;		// Texto descriptivo de la respuesta (Ej.: "OK", "Not modified", etc.)
	DwrString * content_type;	// Tipo de contenido en la respuesta (Ej.: "text/html", "application/javascript", etc.)

	/* tcp ipoque */
	u32 next_tcp_seq_nr[2];
    u32 seq;
    u32 ack_seq;

	/* tcp flags */
	u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1;

	struct response_st * next;		// referencia a otra URL ligada a la URL del nodo cabecera

	/* FUNCIONES */
	/* Actualiza campos del tipo DwrString */
	struct response_st * (*update_text_field) (struct response_st *,
			const char *, ipoque_int_one_line_struct_t *);
	/* Imprime request */
	void (* print) (struct response_st *);
};
typedef struct response_st Http_Response;


/*
 * Nodo cabecera / slots / buckets
 */
struct dwr_headnode_st
{
	void * key;						// Identificador único del headnode (key)
	unsigned req_len;				// Cantidad de requests ligados al headnode
	unsigned rsp_len;				// Cantidad de responses ligados al headnode
	Http_Request * req_start;		// Puntero al primer elemento de la lista enlazada de solicitudes HTTP
	Http_Request * req_end;			// Puntero al último elemento de la lista enlazada de solicitudes HTTP
	Http_Response * rsp_start;		// Puntero al primer elemento de la lista enlazada de respuestas HTTP
	Http_Response * rsp_end;		// Puntero al último elemento de la lista enlazada de respuestas HTTP
	struct dwr_headnode_st * next;	// Puntero al siguiente headnode

	/* FUNCIONES */
	/* Compara el key del headnode con otro key */
	unsigned (* compare) (struct dwr_headnode_st *, void *);
	/* Cambia el key de un headnode */
	struct dwr_headnode_st * (* update_key) (struct dwr_headnode_st *, void *);
	/* Agrega un request a un head, recibe un key, y un request, retorna puntero al request? */
	Http_Request * (* add_request) (struct dwr_headnode_st *, Http_Request *);
	/* Agrega un response a un head, recibe un key, y un request, retorna puntero al request? */
	Http_Response * (* add_response) (struct dwr_headnode_st *, Http_Response *);
	/* Imprime headnode */
	void (* print) (struct dwr_headnode_st *);
};
typedef struct dwr_headnode_st Dwr_Headnode;

/*
 * Lista de adyacencia
 */
struct adj_list_st
{
	Dwr_Headnode * heads;	// Array de elementos de cabecera
	unsigned heads_len;	// Cantidad de headnodes en el grafo

	/* FUNCIONES */
	/* Búsqueda de un headnode por el key, retorna puntero al headnode? */
	Dwr_Headnode * (* search) (struct adj_list_st * self, void *);
	/* Agrega un headnode a la lista, recibe un key, retorna puntero al headnode? */
	Dwr_Headnode * (* add_head) (struct adj_list_st *, void *);
	/* Imprime lista de adyacencia */
	void (* print) (struct adj_list_st *);
};
typedef struct adj_list_st Dwr_Adj_List;




/******************************************************************
 * "CONSTRUCTORES"
 ******************************************************************/
Dwr_Adj_List *
dwr_adj_list_create();

Dwr_Headnode *
dwr_headnode_create();

Http_Response *
dwr_response_create();

Http_Request *
dwr_request_create();

/******************************************************************
 * SEARCH
 ******************************************************************/
/*
 * Return:
 * 	Puntero al headnode, en caso de existir
 * 	NULL, en caso de no encontrar el headnode
 */
Dwr_Headnode *
dwr_adj_list_search_headnode_ptr(Dwr_Adj_List * self, void * arg_key);


/******************************************************************
 * COMPARE
 ******************************************************************/
/*
 * Return:
 * 	0, si key iguales
 * 	1, caso contrario
 */
unsigned
dwr_headnode_key_compare(Dwr_Headnode * self, void * arg_key);


/******************************************************************
 * ADD
 ******************************************************************/

/*
 * Recibe un key ya creado
 */
Dwr_Headnode *
dwr_adj_list_headnode_add(Dwr_Adj_List * self, void * arg_key);



/*
 * Recibe un HttpRequest ya creado
 * Return:
 * 	puntero al request recién insertado
 */
Http_Request *
dwr_headnode_request_add(Dwr_Headnode * self, Http_Request * req);

/*
 * Recibe un HttpResponse ya creado
 * Return:
 * 	puntero al response recién insertado
 */
Http_Response *
dwr_headnode_response_add(Dwr_Headnode * self, Http_Response * rsp);

/******************************************************************
 * UPDATE
 ******************************************************************/

Dwr_Headnode *
dwr_headnode_key_update(Dwr_Headnode * self, void * arg_key);

Dwr_Headnode *
dwr_headnode_methods_update(Dwr_Headnode * h);

/*
 * Actualiza campos que son de texto
 * Param:
 * 	field: nombre del campo a ser cargado
 * 	value: contenido a ser cargado en el campo
 */
Http_Request *
dwr_request_update(Http_Request * req, const char * field, ipoque_int_one_line_struct_t * value);

/*
 * Actualiza campos que son de texto
 * Param:
 * 	field: nombre del campo a ser cargado
 * 	value: contenido a ser cargado en el campo
 */
Http_Response *
dwr_response_update(Http_Response * rsp, const char * field, ipoque_int_one_line_struct_t * value);


/******************************************************************
 * PRINT
 ******************************************************************/
void
dwr_headnode_print(Dwr_Headnode * h);

void
dwr_adj_list_print(Dwr_Adj_List * l);

void
dwr_request_print(Http_Request * req);

void
dwr_response_print(Http_Response * rsp);
#endif
